#define _GNU_SOURCE
#include "app_serial.h"
#include "log/log.h"

int app_serial_init(Device *device)
{
    app_serial_setBaudRate(device, BR_9600); // 蓝牙初始波特率9600
    app_serial_setBlock(device, 0);          // 初始化蓝牙需要测试蓝牙是否可用，为非阻塞模式，连接好后改为阻塞模式

    app_serial_setParity(device, Parity_NONE);
    app_serial_setStopBits(device, SB_1);
    app_serial_setRaw(device);
    // 刷新串口设置
    int result = tcflush(device->fd, TCIOFLUSH);
    if (result == -1)
    {
        log_error("串口初始化设置失败");
        return -1;
    }
    log_debug("串口初始化设置成功");
    return 0;
}

int app_serial_setBaudRate(Device *device, BaudRate_t baudrate)
{
    struct termios attr;

    // 获取串口属性
    tcgetattr(device->fd, &attr);
    // 修改串口属性
    cfsetispeed(&attr, baudrate);
    // 设置串口属性

    int result = tcsetattr(device->fd, TCSAFLUSH, &attr);
    if (result == -1)
    {
        log_error("set baudrate failed");
    }
    log_debug("set baudrate success");
    return 0;
}

int app_serial_setParity(Device *device, Parity_t parity)
{
    struct termios attr;

    // 获取串口属性
    tcgetattr(device->fd, &attr);
    // 修改串口属性
    attr.c_cflag &= ~(PARENB | PARODD); // 清除校验位
    attr.c_cflag |= parity;             // 设置校验位

    // 设置串口属性

    int result = tcsetattr(device->fd, TCSAFLUSH, &attr);
    if (result == -1)
    {
        log_error("set parity failed");
    }
    log_debug("set parity success");
    return 0;
}

int app_serial_setStopBits(Device *device, StopBits_t stopbits)
{
    struct termios attr;

    // 获取串口属性
    tcgetattr(device->fd, &attr);
    // 修改串口属性
    attr.c_cflag &= ~CSTOPB;  // 清除停止位
    attr.c_cflag |= stopbits; // 设置停止位
    // 设置串口属性

    int result = tcsetattr(device->fd, TCSAFLUSH, &attr);
    if (result == -1)
    {
        log_error("set stopbits failed");
    }
    log_debug("set stopbits success");
    return 0;
}
/// @brief 设置是否为阻塞模式
/// @param device
/// @param is_block
/// @return
int app_serial_setBlock(Device *device, int is_block)
{

    struct termios attr;

    // 获取串口属性
    tcgetattr(device->fd, &attr);
    // 修改串口属性

    if (is_block == 1)
    {
        attr.c_cc[VMIN] = 1;  // 至少读取一个字符
        attr.c_cc[VTIME] = 0; // 没有数据时等待
    }
    else
    {
        attr.c_cc[VMIN] = 0;  // 可以读不到字符
        attr.c_cc[VTIME] = 2; // 等待 2*100ms
    }
    // 设置串口属性

    int result = tcsetattr(device->fd, TCSAFLUSH, &attr);
    if (result == -1)
    {
        log_error("set block failed");
    }
    log_debug("set block success");
    return 0;
}

/// @brief 设置为原始模式
/// @param device
/// @return
int app_serial_setRaw(Device *device)
{
    struct termios attr;

    // 获取串口属性
    tcgetattr(device->fd, &attr);
    // 修改串口属性
    cfmakeraw(&attr);

    // 设置串口属性

    int result = tcsetattr(device->fd, TCSAFLUSH, &attr);
    if (result == -1)
    {
        log_error("set raw failed");
    }
    log_debug("set raw success");
    return 0;
}
